package com.journaldev.threadpool.poolexecutor;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.journaldev.threadpool.WorkerThread;

/**
 * http://blog.csdn.net/defonds/article/details/9715455
 * 使用 ThreadPoolExecutor 的线程池实现demo
 * @author:chenhs E-mail:hson08_chen@163.com
 * Created on 2017年9月8日 上午11:54:32
 *
 * poolSize、corePoolSize、maximumPoolSize三者的关系是如何的呢？
 * 当新提交一个任务时：
 * （1）如果poolSize < coreSize，新增加一个线程处理新的任务。
 * （2）如果poolSize = coreSize，新任务会被放入阻塞队列等待。
 * （3）如果阻塞队列的容量达到上限，且这时poolSize < maximumPoolSize，新增线程来处理任务。
 * （4）如果阻塞队列满了，且poolSize = maximumPoolSize，那么线程池已经达到极限，会根据饱和策略RejectedExecutionHandler拒绝新的任务。
 *
 */
public class WorkerPool {

	public static void main(String[] args) throws InterruptedException {
		RejectedExecutionHandlerImpl rejectedHandler = new RejectedExecutionHandlerImpl();
		
		ThreadFactory threadFactory = Executors.defaultThreadFactory();
		/**
		corePoolSize	核心线程池大小
		maximumPoolSize	最大线程池大小
		keepAliveTime	线程池中超过corePoolSize数目的空闲线程最大存活时间；可以allowCoreThreadTimeOut(true)使得核心线程有效时间
		TimeUnit		keepAliveTime时间单位
		workQueue		阻塞任务队列
		threadFactory	新建线程工厂
		RejectedExecutionHandler	当提交任务数超过maxmumPoolSize+workQueue之和时，任务会交给RejectedExecutionHandler来处理
		*/
		ThreadPoolExecutor executorPool = new ThreadPoolExecutor(2, 4, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(2), threadFactory, rejectedHandler);

		MyMonitorThread monitor = new MyMonitorThread(executorPool, 3);
		Thread monitorThread = new Thread(monitor);
		monitorThread.start();
		
		for(int i=0; i < 10; i++){
			executorPool.execute(new WorkerThread("cmd"+ i));
		}
		
		Thread.sleep(30000);
		executorPool.shutdown();	// This will make the executor accept no new threads and finish all existing threads in the queue
		
		try {
			// 最大等待时间（秒），防止一直无限循环下去。
			int timeout = 300;
			// 每次检查超时时间
			int waittime = 2;
			boolean loop = true;
			do {
				// 循环检查线程池中所有任务是否都完成，
				loop = !executorPool.awaitTermination(waittime, TimeUnit.SECONDS);	// Wait until all threads are finish,and also you can use "executor.awaitTermination();" to wait
				timeout = timeout - waittime;
			} while (loop && timeout > 0);
			System.out.println("线程池所有任务已经完成。timeout=" + timeout);
		} catch (InterruptedException e) {
			throw new InterruptedException( "导出文件出现异常！");
		}
		
	}

}
